package com.ruoyi.common.DataConversion.service.Impl;

import com.ruoyi.common.DataConversion.UpReadParamAllPackage;
import com.ruoyi.common.DataConversion.UpReadParamNewPackage;
import com.ruoyi.common.DataConversion.UpWriteParametersNewPackage;
import com.ruoyi.common.DataConversion.domain.AgreementAnalysisV2;
import com.ruoyi.common.DataConversion.service.DeviceParameterMonitoringService;
import com.ruoyi.common.domin.MainObject;
import com.ruoyi.common.domin.TypeConvertUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.Socket;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * @ClassName DownStationInfoServiceImpl
 * @Description 分站信息下发服务实现
 * @Author 张永永
 * @Date 2020-12-26 16:38
 * @Version 1.0.0.0
 **/
@Service
public class DeviceParameterMonitoringServiceImpl implements DeviceParameterMonitoringService {


    @Autowired
    private AgreementAnalysisV2 agreementAnalysis2;

    //创建日志对象 Logger
    static final Logger logger = LogManager.getLogger(DeviceParameterMonitoringServiceImpl.class);


    /**
     * 读取分站参数信息 todo
     *
     * @param startAddress 起始地址
     * @param dataLength   数据长度
     * @param stationParam 填充的参数实体
     * @return
     */
    @Override
    public Map<String, Object> readStationParam(String deviceIp, String startAddress, int dataLength, Object stationParam) {
        try {
            Callable myCallable = (Callable<Object>) () -> {

                //随机生成4为数字 当作唯一码
                String uniqueBaseCode = generateRandom4Digit();

                //=========================生成读参数数据包======================================

                //包体数据
                byte[] bodyBaseBytes = agreementAnalysis2.packReadParam(uniqueBaseCode, startAddress, dataLength);
                //包头数据
                byte[] headerBaseBytes = agreementAnalysis2.packPackageHeader("03", bodyBaseBytes.length);

                headerBaseBytes = agreementAnalysis2.packPackageHeader("03", bodyBaseBytes.length+headerBaseBytes.length);

                //数据包
                byte[] packageBaseBytes = TypeConvertUtils.concatBytes(headerBaseBytes, bodyBaseBytes);

                //生成分站基本参数下行帧
                byte[] downFrameBytes = agreementAnalysis2.createDownFrame(headerBaseBytes, bodyBaseBytes);
                //下发数据

                Socket socket = null;

                socket = MainObject.tcpServer.getIpAddressMapSocket().get(deviceIp);

                String sendResult = MainObject.tcpServer.sendData(socket, downFrameBytes);
                if (true == sendResult.equals("0")) {
                    HashMap<String, Object> failureMap = new HashMap<>();
                    failureMap.put("ReceiveResult", "设备已离线，操作未下发");
                    failureMap.put("ResultContent", null);//返回内容
                    failureMap.put("ReceiveTime", new Date());
                    return failureMap;
                }

                MainObject.REDERPARAM.put(uniqueBaseCode, null);

                //时间计数器
                int timeNum = 0;
                //循环读取返回值
                while (true) {
                    Thread.sleep(1000);
                    //读取读参数包
                    UpReadParamNewPackage paramPackage = MainObject.REDERPARAM.get(uniqueBaseCode);
                    //如果小于2秒且状态为成功
                    if (timeNum < 20
                            && paramPackage != null) {
                        //===========================数据库记录信息===================================
                        HashMap<String, Object> successMap = new HashMap<>();
                        int dataContentLength = paramPackage.dataContent.length;
                        int dataContent = TypeConvertUtils.bytesToReverseInt(paramPackage.dataContent);
                        //如果数据长度等于1，则返回错误码
                        if (dataContentLength == 1) {
//                            successMap.put("ReceiveResult", MainObject.ERROR_CODE_DESCRIPTION.get(errorCode));
                            successMap.put("ResultContent", null);
                        } else {
                            successMap.put("ReceiveResult", "操作成功");

                            // 转换为无符号的 16 进制数
                            StringBuilder hexString = new StringBuilder();
                            for (byte b : paramPackage.getDataContent()) {
                                // 将 byte 转换为无符号的 int
                                int unsignedByte = b & 0xFF;
                                // 将无符号的 int 转换为 16 进制字符串，并确保两位
                                String hex = String.format("%02X", unsignedByte);
                                hexString.append(hex);
                            }
                            //解析检修模式
                            if (startAddress.equals("808"))
                            {
                                if (dataContent==85){
                                    successMap.put("ResultContent", "开启");//返回内容
                                }else if (dataContent==170){
                                    successMap.put("ResultContent", "关闭");//返回内容
                                }

                            }else {

                                if(startAddress.equals("1c") || startAddress.equals("18")){
                                    successMap.put("ResultContent", dataContent);//返回内容

                                }else {
                                    // 将 int 转换为 Double
                                    double dataContentDouble = (double) dataContent;

                                    // 进行除法运算
                                    double result = dataContentDouble / 10.0;

                                    // 将结果转换为字符串，并处理整数部分
                                    String finalResult = formatDouble(result);
                                    successMap.put("ResultContent", finalResult);//返回内容

                                }


                            }
                        }
//                        successMap.put("ID", uniqueId);
                        successMap.put("ReceiveTime", new Date());

//                        downStationInfoMapper.updateDownStationInfo(successMap);
                        //移除该键
                        MainObject.REDERPARAM.remove(uniqueBaseCode);
                        return successMap;
                    }
                    //如果大于2秒
                    if (timeNum >= 20) {

                        //===========================数据库记录时钟同步信息===================================
                        HashMap<String, Object> failureMap = new HashMap<>();

                        //移除该键
                        MainObject.REDERPARAM.remove(uniqueBaseCode);
                        return failureMap;
                    }
                    timeNum++;
                }
            };
            //根据代码段实例创建一个未来任务
            FutureTask<Object> future = new FutureTask<Object>(myCallable);
            //运行任务
            future.run();
            HashMap<String, Object> returnMap = (HashMap<String, Object>) future.get();
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("ReceiveResult", returnMap.get("ReceiveResult"));
            resultMap.put("ResultContent", returnMap.get("ResultContent"));
            return resultMap;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
    /**
     * 读取分站参数信息 todo
     *
     * @param startAddress 起始地址
     * @param dataLength   数据长度
     * @param stationParam 填充的参数实体
     * @return
     */
    @Override
    public Map<String, Object> readStationAllParam( String deviceIp, String startAddress, int dataLength, Object stationParam) {
    {
        try {
            Callable myCallable = (Callable<Object>) () -> {

                //分站编号
                //TODO

                //=========================生成读参数数据包======================================
                String uniqueBaseCode = generateRandom4Digit();
//                String uniqueBaseCode = "0001";
                //包体数据
                byte[] bodyBaseBytes = agreementAnalysis2.packReadParam(uniqueBaseCode, startAddress, dataLength);
                //包头数据
                byte[] headerBaseBytes = agreementAnalysis2.packPackageHeader("03", bodyBaseBytes.length);

                headerBaseBytes = agreementAnalysis2.packPackageHeader("03", bodyBaseBytes.length+headerBaseBytes.length);

                //数据包
                byte[] packageBaseBytes = TypeConvertUtils.concatBytes(headerBaseBytes, bodyBaseBytes);

                //生成分站基本参数下行帧
                byte[] downFrameBytes = agreementAnalysis2.createDownFrame(headerBaseBytes, bodyBaseBytes);
                //下发数据

                Socket socket = null;
//                if (filterStation.size() > 0) {
//                    socket = MainObject.tcpServer.getIpAddressMapSocket().get(filterStation.get(0).get("IP"));
//                }

                socket = MainObject.tcpServer.getIpAddressMapSocket().get(deviceIp);

                String sendResult = MainObject.tcpServer.sendData(socket, downFrameBytes);
                if (true == sendResult.equals("0")) {
                    HashMap<String, Object> failureMap = new HashMap<>();
                    failureMap.put("ReceiveResult", "设备已离线，操作未下发");
                    failureMap.put("ResultContent", null);//返回内容
                    failureMap.put("ReceiveTime", new Date());
                    return failureMap;
                }

                MainObject.REDERALLPARAM.put(uniqueBaseCode, null);

                //时间计数器
                int timeNum = 0;
                //循环读取返回值
                while (true) {
                    Thread.sleep(1000);
                    //读取读参数包
                    UpReadParamAllPackage paramPackage = MainObject.REDERALLPARAM.get(uniqueBaseCode);
                    //如果小于2秒且状态为成功
                    if (timeNum < 20
                            && paramPackage != null) {
                        //===========================数据库记录信息===================================
                        HashMap<String, Object> successMap = new HashMap<>();
                        int dataContentLength = paramPackage.dataContent.length;
                        int dataContent = TypeConvertUtils.bytesToReverseInt(paramPackage.dataContent);
                        //如果数据长度等于1，则返回错误码
                        if (dataContentLength == 1) {
//                            successMap.put("ReceiveResult", MainObject.ERROR_CODE_DESCRIPTION.get(errorCode));
                            successMap.put("ResultContent", null);
                        } else {
                            successMap.put("ReceiveResult", "操作成功");
                            //解析基本参数
//                            JavaStruct.unpack(stationParam, paramPackage.dataContent, ByteOrder.LITTLE_ENDIAN);

                            // 转换为无符号的 16 进制数
                            StringBuilder hexString = new StringBuilder();
                            for (byte b : paramPackage.getDataContent()) {
                                // 将 byte 转换为无符号的 int
                                int unsignedByte = b & 0xFF;
                                // 将无符号的 int 转换为 16 进制字符串，并确保两位
                                String hex = String.format("%02X", unsignedByte);
                                hexString.append(hex);
                            }
//                            String littleEndianHexString = hexString.reverse().toString();
                            successMap.put("ResultContent", dataContent);//返回内容
                        }
//                        successMap.put("ID", uniqueId);
                        successMap.put("ReceiveTime", new Date());

//                        downStationInfoMapper.updateDownStationInfo(successMap);
                        //移除该键
                        MainObject.REDERALLPARAM.remove(uniqueBaseCode);
                        return successMap;
                    }
                    //如果大于2秒
                    if (timeNum >= 20) {

                        //===========================数据库记录时钟同步信息===================================
                        HashMap<String, Object> failureMap = new HashMap<>();

                        //移除该键
                        MainObject.REDERALLPARAM.remove(uniqueBaseCode);
                        return failureMap;
                    }
                    timeNum++;
                }
            };
            //根据代码段实例创建一个未来任务
            FutureTask<Object> future = new FutureTask<Object>(myCallable);
            //运行任务
            future.run();
            HashMap<String, Object> returnMap = (HashMap<String, Object>) future.get();
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("ReceiveResult", returnMap.get("ReceiveResult"));
            resultMap.put("ResultContent", returnMap.get("ResultContent"));
            return resultMap;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
    }

    /**
     * 下发分站地址写指令  todo
     *
     * @param deviceIp    设备Ip
     * @param startAddress 下发起始地址
     * @param dataContent  下发内容
     * @return
     */
    @Override
    public Map<String, Object> writeStationParam(String deviceIp, String startAddress, int dataContent) {
        try {
            Callable myCallable = (Callable<String>) () -> {


                //=======================生成下发内容==========================================

                byte[] contentBytes = TypeConvertUtils.intToConverseBytes(dataContent, 4);
                //===============================================================================
                //=========================生成写入数据============================================

                String uniqueCode = generateRandom4Digit();
                //包体数据
                byte[] bodyDateBytes = agreementAnalysis2.packWriteParam(uniqueCode, startAddress, contentBytes);
                //包头数据
                byte[] headerDateBytes = agreementAnalysis2.packPackageHeader("10", bodyDateBytes.length);

                headerDateBytes = agreementAnalysis2.packPackageHeader("10", bodyDateBytes.length+headerDateBytes.length);
                //数据包
                byte[] packageDateBytes = TypeConvertUtils.concatBytes(headerDateBytes, bodyDateBytes);

                //生成日期和时间下行帧
                byte[] downFrameBytes = agreementAnalysis2.createDownFrame(headerDateBytes, bodyDateBytes);
                // 将 byte[] 转换成 16 进制字符串
                String hexString = bytesToHex(downFrameBytes);

                // 输出结果
                System.out.println("Byte array in hexadecimal format: " + hexString);
                //下发数据
                Socket socket = null;
//                if (filterStation.size() > 0) {
//                    socket = MainObject.tcpServer.getIpAddressMapSocket().get(filterStation.get(0).get("IP"));
//                }
                socket = MainObject.tcpServer.getIpAddressMapSocket().get(deviceIp);

                String sendResult = MainObject.tcpServer.sendData(socket, downFrameBytes);
                if (true == sendResult.equals("0")) {
                    return "分站已离线，操作未下发";
                }

                MainObject.WRITE_PARAM_SEND_RECEIVER_MAP.put(uniqueCode, null);


                //时间计数器
                int timeNum = 0;
                //循环读取返回值
                while (true) {
                    Thread.sleep(1000);
                    //读取写参数包
                    UpWriteParametersNewPackage paramPackage = MainObject.WRITE_PARAM_SEND_RECEIVER_MAP.get(uniqueCode);

                    //如果小于2秒且状态为成功
                    if (timeNum < 20
                            && paramPackage != null) {

                        //移除该键
                        MainObject.WRITE_PARAM_SEND_RECEIVER_MAP.remove(uniqueCode);
                        return paramPackage.getResult();
                    }
                    //如果大于2秒
                    if (timeNum >= 20) {

                        //移除该键
                        MainObject.WRITE_PARAM_SEND_RECEIVER_MAP.remove(uniqueCode);
                        return "操作超时或失败";
                    }
                    timeNum++;
                }
            };
            //根据代码段实例创建一个未来任务
            FutureTask<String> future = new FutureTask<String>(myCallable);
            //运行任务
            future.run();

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("result", future.get());

            return resultMap;
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * CN：生成一个4位的随机数。
     * EN：Generates a 4-digit random number.
     *
     * @return
     * CN：生成的4位随机数。
     * EN：The generated 4-digit random number.
     */
    public static String generateRandom4Digit() {
        Random random = new Random();
        int randomNum = random.nextInt(9999); // 生成0到9999之间的随机数
        return String.format("%04d", randomNum); // 确保是4位数，不足4位前面补0
    }


    /**
     * 将 byte[] 转换成 16 进制字符串。
     *
     * @param bytes 字节数组
     * @return 字节数组的 16 进制字符串表示
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0'); // 补零
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }



    /**
     * 将 Double 类型的值转换为字符串，并处理整数部分
     * Convert a Double value to a string and handle the integer part
     *
     * @param value 需要转换的 Double 值
     *               The Double value to convert
     * @return 转换后的字符串
     *         The converted string
     */
    public static String formatDouble(double value) {
        // 如果值是整数，则返回整数部分
        if (value == Math.floor(value) && !Double.isInfinite(value)) {
            return String.valueOf((int) value);
        } else {
            // 否则返回原始值的字符串表示
            return String.valueOf(value);
        }
    }

}
